use crate::util::{channel_new_custom};
use tokio::runtime::Runtime;
use crate::util::{SyncSender,SyncRecv};
use std::sync::RwLock;

lazy_static!{
    static ref DYN_RUNTIME_CHANNEL: ((SyncSender<DynRuntimeMsg>, SyncRecv<DynRuntimeMsg>),
        (SyncSender<Runtime>, SyncRecv<Runtime>)) = {
        (channel_new_custom(1),channel_new_custom(1))
    };
    static ref DYN_RUNTIME_LOCK: RwLock<()> = RwLock::new(());
}

pub enum DynRuntimeMsg{
    New(String,usize),
    Drop(Runtime),
}

pub fn dyn_runtime_run(){

    let r = std::thread::spawn(||{
        info!("dyn_runtime_run");

        loop{
            let msg = DYN_RUNTIME_CHANNEL.0.1.recv();
            info!("dyn_runtime_run get msg");

            match msg{
                DynRuntimeMsg::Drop(r) => {drop(r);},
                DynRuntimeMsg::New(name,threads) => {
                    match tokio::runtime::Builder::new_multi_thread()
                        .thread_name(name)
                        .worker_threads(threads)
                        .build(){
                        Result::Ok(t) => {
                            DYN_RUNTIME_CHANNEL.1.0.send(t);
                        },
                        Result::Err(e) => {
                            let err_desc = format!("dyn_runtime build failed [{:?}]", e);
                            std::process::exit(-1);
                        },
                    }
                },
            }
        }
    });
}

pub fn dyn_new_runtime(name: &str, threads: usize)->Runtime{
    info!("dyn_new_runtime {} {}", name, threads);

    if let Ok(dyn_runtime_lock) = DYN_RUNTIME_LOCK.write(){
        DYN_RUNTIME_CHANNEL.0.0.send(DynRuntimeMsg::New(name.to_string(), threads));

        return DYN_RUNTIME_CHANNEL.1.1.recv();
    }else{
        error!("DYN_RUNTIME_LOCK write err");
        std::process::exit(-1);
    }
}
